<?php

/**
 * Radcodes - SocialEngine Module
 *
 * @category   Application_Extensions
 * @package    Badge
 * @copyright  Copyright (c) 2009-2010 Radcodes LLC (http://www.radcodes.com)
 * @license    http://www.radcodes.com/license/
 * @version    $Id$
 * @author     Vincent Van <vincent@radcodes.com>
 */

class Badge_Model_Badge extends Core_Model_Item_Abstract {
	
	const MEMBERSHIP_TYPE_AWARD = 'award';
	const MEMBERSHIP_TYPE_MAPPING = 'mapping';
	
	// Properties
	

	protected $_searchTriggers = array ('search', 'title', 'description' );
	
	/**
	 * Gets an absolute URL to the page to view this item
	 *
	 * @return string
	 */
	public function getHref($params = array()) {
		$slug = $this->getSlug ();
		
		$params = array_merge ( array ('route' => 'badge_profile', 'reset' => true, 'badge_id' => $this->badge_id, 'slug' => $slug ), $params );
		$route = $params ['route'];
		$reset = $params ['reset'];
		unset ( $params ['route'] );
		unset ( $params ['reset'] );
		return Zend_Controller_Front::getInstance ()->getRouter ()->assemble ( $params, $route, $reset );
	}
	
	public function getCategory() {
		return Engine_Api::_ ()->badge ()->getCategory ( $this->category_id );
	}
	
	// Interfaces
	/**
	 * Gets a proxy object for the comment handler
	 *
	 * @return Engine_ProxyObject
	 **/
	public function comments() {
		return new Engine_ProxyObject ( $this, Engine_Api::_ ()->getDbtable ( 'comments', 'core' ) );
	}
	
	/**
	 * Gets a proxy object for the like handler
	 *
	 * @return Engine_ProxyObject
	 **/
	public function likes() {
		return new Engine_ProxyObject ( $this, Engine_Api::_ ()->getDbtable ( 'likes', 'core' ) );
	}
	
	protected function _delete() {
		if ($this->_disableHooks)
			return;
		
		// remove all awards
		$paginator = $this->getAwardsPaginator ();
		foreach ( $paginator as $award ) {
			$award->delete ();
		}
		
		$paginator = Engine_Api::_ ()->badge ()->getRequestsPaginator ( array ('badge' => $this ) );
		foreach ( $paginator as $request ) {
			$request->delete ();
		}
		
		parent::_delete ();
	}
	
	public function setPhoto($photo) {
		if ($photo instanceof Zend_Form_Element_File) {
			$file = $photo->getFileName ();
		} else if ($photo instanceof Storage_Model_File) {
			$file = $photo->temporary ();
		} else if ($photo instanceof Core_Model_Item_Abstract && ! empty ( $photo->file_id )) {
			$file = Engine_Api::_ ()->getItem ( 'storage_file', $photo->file_id )->temporary ();
		} else if (is_array ( $photo ) && ! empty ( $photo ['tmp_name'] )) {
			$file = $photo ['tmp_name'];
		} else if (is_string ( $photo ) && file_exists ( $photo )) {
			$file = $photo;
		} else {
			throw new Badge_Model_Exception ( 'invalid argument passed to setPhoto' );
		}
		
		$this->removePhoto ();
		
		$name = basename ( $file );
		$path = APPLICATION_PATH . DIRECTORY_SEPARATOR . 'temporary';
		$params = array ('parent_type' => $this->getType (), 'parent_id' => $this->getIdentity () );
		
		// Save
		$storage = Engine_Api::_ ()->storage ();
		
		// Resize image (main)
		$image = Engine_Image::factory ();
		$image->open ( $file )->resize ( 720, 720 )->write ( $path . '/m_' . $name )->destroy ();
		
		// Resize image (profile)
		$image = Engine_Image::factory ();
		$image->open ( $file )->resize ( 180, 240 )->write ( $path . '/p_' . $name )->destroy ();
		
		// Resize image (normal)
		$image = Engine_Image::factory ();
		$image->open ( $file )->resize ( 140, 160 )->write ( $path . '/in_' . $name )->destroy ();
		
		// Resize image (icon)
		$image = Engine_Image::factory ();
		$image->open ( $file );
		
		$size = min ( $image->height, $image->width );
		$x = ($image->width - $size) / 2;
		$y = ($image->height - $size) / 2;
		
		$image->resample ( $x, $y, $size, $size, 48, 48 )->write ( $path . '/is_' . $name )->destroy ();
		
		// Resize image (mini)
		$image = Engine_Image::factory ();
		$image->open ( $file );
		
		$size = min ( $image->height, $image->width );
		$x = ($image->width - $size) / 2;
		$y = ($image->height - $size) / 2;
		
		$image->resample ( $x, $y, $size, $size, 16, 16 )->write ( $path . '/imn_' . $name )->destroy ();
		
		// Store
		$iMain = $storage->create ( $path . '/m_' . $name, $params );
		$iProfile = $storage->create ( $path . '/p_' . $name, $params );
		$iIconNormal = $storage->create ( $path . '/in_' . $name, $params );
		$iSquare = $storage->create ( $path . '/is_' . $name, $params );
		$iMini = $storage->create ( $path . '/imn_' . $name, $params );
		
		$iMain->bridge ( $iProfile, 'thumb.profile' );
		$iMain->bridge ( $iIconNormal, 'thumb.normal' );
		$iMain->bridge ( $iSquare, 'thumb.icon' );
		$iMain->bridge ( $iMini, 'thumb.mini' );
		
		// Remove temp files
		@unlink ( $path . '/p_' . $name );
		@unlink ( $path . '/m_' . $name );
		@unlink ( $path . '/in_' . $name );
		@unlink ( $path . '/is_' . $name );
		@unlink ( $path . '/imn_' . $name );
		
		// Update row
		$this->photo_id = $iMain->file_id;
		$this->save ();
		
		return $this;
	}
	
	public function removePhoto() {
		if (empty ( $this->photo_id )) {
			return;
		}
		
		$types = array (null, 'thumb.profile', 'thumb.normal', 'thumb.icon', 'thumb.mini' );
		foreach ( $types as $type ) {
			$file = $this->api ()->getApi ( 'storage', 'storage' )->get ( $this->photo_id, $type );
			if ($file) {
				$file->remove ();
			}
		}
		
		$this->photo_id = 0;
	}
	
	public function membershipCount($params = array()) {
		$total = 0;
		
		if ($this->isMembershipTypeAward ()) {
			$total = $this->countAwards ( $params );
		} else if ($this->isMembershipTypeMapping ()) {
			$total = $this->countMembers ( $params );
		}
		
		return $total;
	}
	
	public function isMembershipType($type) {
		return $this->membership_type == $type;
	}
	
	public function isMembershipTypeAward() {
		return $this->isMembershipType ( self::MEMBERSHIP_TYPE_AWARD );
	}
	
	public function isMembershipTypeMapping() {
		return $this->isMembershipType ( self::MEMBERSHIP_TYPE_MAPPING );
	}
	
	public function countAwards($params = array()) {
		$paginator = $this->getAwardsPaginator ( $params );
		return $paginator->getTotalItemCount ();
	}
	
	public function getAwardsPaginator($params = array()) {
		$params = array_merge ( array ('badge' => $this, 'order' => $this->awards_order ), $params );
		
		$paginator = Engine_Api::_ ()->badge ()->getAwardsPaginator ( $params );
		return $paginator;
	}
	
	public function isAwardedMember($user, $active = null) {
		$params = array ('user' => $user, 'limit' => 1 );
		if ($active !== null) {
			$params ['active'] = $active;
		}
		$paginator = $this->getAwardsPaginator ( $params );
		return $paginator->getTotalItemCount () > 0;
	}
	
	public function getSampleMemberUsers($limit = 3) {
		$users = array ();
		
		$params = array ('limit' => $limit );
		
		if ($this->isMembershipTypeAward ()) {
			$awards = $this->getAwardsPaginator ( $params );
			foreach ( $awards as $award ) {
				$users [] = $award->getUser ();
			}
		} else if ($this->isMembershipTypeMapping ()) {
			$members = $this->getMembersPaginator ( $params );
			foreach ( $members as $member ) {
				$users [] = $member;
			}
		}
		
		return $users;
	}
	
	public function countMembers($params = array()) {
		$paginator = $this->getMembersPaginator ( $params );
		return $paginator->getTotalItemCount ();
	}
	
	public function getMembersPaginator($params = array()) {
		$paginator = Zend_Paginator::factory ( $this->getMembersSelect ( $params ) );
		if (! empty ( $params ['page'] )) {
			$paginator->setCurrentPageNumber ( $params ['page'] );
		}
		if (! empty ( $params ['limit'] )) {
			$paginator->setItemCountPerPage ( $params ['limit'] );
		}
		return $paginator;
	}
	
	public function getMembersSelect($params = array()) {
		// Get table info
		$table = Engine_Api::_ ()->getItemTable ( 'user' );
		$userTableName = $table->info ( 'name' );
		
		// Contruct query
		$select = $table->select ()->//->setIntegrityCheck(false)
		from ( $userTableName );
		
		$select->where ( "{$userTableName}.enabled = ?", 1 );
		
		$exclude_user_ids = trim ( str_replace ( " ", "", trim ( $this->exclude_user_ids ) ), ',' );
		if (strlen ( $exclude_user_ids )) {
			$select->where ( "{$userTableName}.user_id NOT IN (?)", explode ( ',', $exclude_user_ids ) );
		}
		
		if ($this->user_profile_photo) {
			$select->where ( $userTableName . '.photo_id != ?', "0" );
		}
		
		if ($this->user_view_count) {
			$select->where ( $userTableName . '.view_count >= ?', $this->user_view_count );
		}
		
		if ($this->user_invites_used) {
			$select->where ( $userTableName . '.invites_used >= ?', $this->user_invites_used );
		}
		
		$today_date = date ( "Y-m-d H:i:s" );
		if ($this->user_account_age) {
			$select->where ( "DATEDIFF('$today_date', $userTableName.creation_date) >= ?", ( int ) $this->user_account_age );
		}
		
		if ($this->user_login_days) {
			$select->where ( "$userTableName.lastlogin_date IS NOT NULL AND DATEDIFF('$today_date', $userTableName.lastlogin_date) <= ?", ( int ) $this->user_login_days );
		}
		
		if ($this->user_level_settings) {
			$select->where ( $userTableName . '.level_id IN (?)', $this->user_level_ids );
		}
		
		if ($this->user_profile_settings) {
			$valueTable = Engine_Api::_ ()->fields ()->getTable ( 'user', 'values' );
			$valueTableName = $valueTable->info ( 'name' );
			
			$fieldsByAlias = Engine_Api::_ ()->fields ()->getFieldsObjectsByAlias ( 'user', 'profile_type' );
			
			if (! empty ( $fieldsByAlias ['profile_type'] )) {
				$select->joinLeft ( $valueTableName, "`{$valueTableName}`.`item_id` = `{$userTableName}`.`user_id`", null );
				$select->where ( "`{$valueTableName}`.`field_id` = ?", $fieldsByAlias ['profile_type']->field_id );
				$select->where ( "`{$valueTableName}`.`value` IN (?)", $this->user_profile_ids );
			
		//print_r($fieldsByAlias['profile_type']->toArray());
			/*Field_Model_Meta
					Array ( [field_id] => 1 [type] => profile_type [label] => Profile Type [description] => [alias] => profile_type [required] => 1 [display] => 0 [publish] => 0 [search] => 2 [show] => 1 [order] => 999 [config] => [validators] => [filters] => [style] => [error] => ) 
         */
			//$optionId = $fieldsByAlias['profile_type']->getValue($user);      
			}
		
		}
		
		if ($this->user_network_settings) {
			$networkTable = Engine_Api::_ ()->getDbtable ( 'membership', 'network' );
			$networkTableName = $networkTable->info ( 'name' );
			
			$select->joinLeft ( $networkTableName, "`{$networkTableName}`.`user_id` = `{$userTableName}`.`user_id`", null );
			
			$select->where ( "`{$networkTableName}`.`resource_id` IN (?)", $this->user_network_ids );
		}
		
		$include_user_ids = trim ( str_replace ( " ", "", trim ( $this->include_user_ids ) ), ',' );
		if (strlen ( $include_user_ids )) {
			$select->orWhere ( "{$userTableName}.user_id IN (?)", explode ( ',', $include_user_ids ) );
		}
		
		$select->group ( "{$userTableName}.user_id" );
		
		if (isset ( $params ['order'] )) {
			$select->order ( $params ['order'] );
		} else if ($this->members_order) {
			$select->order ( $this->members_order );
		}
		
		//echo $select;
		

		return $select;
	}
	
	public function testMemberRequirements($user) {
		$errors = $this->checkMemberRequirements ( $user );
		return count ( $errors ) > 0 ? false : true;
	}
	
	public function checkMemberRequirements($user) {
		$user = Engine_Api::_ ()->user ()->getUser ( $user );
		
		$errors = array ();
		
		if (! $user->getIdentity ()) {
			$errors ['user'] = true;
		}
		
		if ($this->user_profile_photo && ! $user->photo_id) {
			$errors ['user_profile_photo'] = true;
		}
		
		if ($this->user_view_count && $this->user_view_count > $user->view_count) {
			$errors ['user_view_count'] = $user->view_count;
		}
		
		if ($this->user_invites_used && $this->user_invites_used > $user->invites_used) {
			$errors ['user_invites_used'] = $user->invites_used;
		}
		
		if ($this->user_account_age && $this->user_account_age * 86400 > (time () - strtotime ( $user->creation_date ))) {
			$errors ['user_account_age'] = ( int ) (time () - strtotime ( $user->creation_date )) / 86400;
		}
		
		if ($this->user_login_days) {
			if (! $user->lastlogin_date) {
				$errors ['user_login_days'] = false;
			} else if ($user->lastlogin_date && $this->user_login_days * 86400 < (time () - strtotime ( $user->lastlogin_date ))) {
				$errors ['user_login_days'] = ( int ) (time () - strtotime ( $user->lastlogin_date )) / 86400;
			}
		}
		
		if ($this->user_level_settings && ! in_array ( $user->level_id, $this->user_level_ids )) {
			$errors ['user_level_settings'] = $user->level_id;
		}
		
		if ($this->user_profile_settings) {
			$fieldsByAlias = Engine_Api::_ ()->fields ()->getFieldsObjectsByAlias ( 'user', 'profile_type' );
			
			if (! empty ( $fieldsByAlias ['profile_type'] )) {
				$optionId = $fieldsByAlias ['profile_type']->getValue ( $user );
				if ($optionId) {
					if (! in_array ( $optionId->value, $this->user_profile_ids )) {
						$errors ['user_profile_settings'] = $optionId->value;
					}
				}
			}
		
		}
		
		if ($this->user_network_settings) {
			$select = Engine_Api::_ ()->getDbtable ( 'membership', 'network' )->getMembershipsOfSelect ( $user )->where ( 'hide = ?', 0 );
			$networks = Engine_Api::_ ()->getDbtable ( 'networks', 'network' )->fetchAll ( $select );
			$network_ids = array ();
			foreach ( $networks as $network ) {
				$network_ids [] = $network->getIdentity ();
			}
			if (count ( array_intersect ( $network_ids, $this->user_network_ids ) ) == 0) {
				$errors ['user_network_settings'] = $network_ids;
			}
		}
		//Zend_Debug::dump($errors);
		return $errors;
	}
	
	public function getInfoMemberLevels() {
		$options = Engine_Api::_ ()->badge ()->getMemberLevelArray ();
		return $this->getInfoMemberOptions ( 'level', $options );
	}
	
	public function getInfoMemberNetworks() {
		$options = Engine_Api::_ ()->badge ()->getNetworkArray ();
		return $this->getInfoMemberOptions ( 'network', $options );
	}
	
	public function getInfoMemberProfiles() {
		$options = Engine_Api::_ ()->badge ()->getProfileTypeArray ();
		return $this->getInfoMemberOptions ( 'profile', $options );
	}
	
	protected function getInfoMemberOptions($type, $options) {
		$info = array ();
		
		if ($this->{"user_{$type}_settings"}) {
			foreach ( $this->{"user_{$type}_ids"} as $id ) {
				if (isset ( $options [$id] )) {
					$info [$id] = $options [$id];
				}
			}
		}
		
		return $info;
	}

}